package com.health.mapp.service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.soap.SOAPFaultException;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.codehaus.jackson.JsonEncoding;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;

import com.health.mapp.service.Adapter4Upload;
import com.health.mapp.service.SecureUtil;
import com.health.commons.CommonsUtils;
import com.health.mapp.bean.Header;
import com.health.mapp.exception.MappException;
import com.health.mapp.impl.ActionInterface;
import com.health.mapp.impl.HeaderCheckImpl;
import com.health.mapp.utils.Constant;
import com.health.mapp.utils.DefaultResponse;
import com.health.mapp.utils.Response;

public class Adapter4Upload {

	private static Logger logger = Logger.getLogger(Adapter4Upload.class);
	private HttpServletRequest request;

	public HttpServletRequest getRequest() {
		return request;
	}

	public void setRequest(HttpServletRequest request) {
		this.request = request;
	}

	/**
	 * @param len
	 *           数据长度
	 * @param buffer
	 *           数据BUFF
	 * @return
	 */
	public String execute(int len, byte[] buffer) {

		//定义返回结果
		String resultJson = null;
		
		//是否使用ECB加密
		boolean useECBCrypto = false;
		
		//报方头对象
		Header headerInfo = new Header();
		//报文体存储空间
		byte[] jsonBuffer = null;
		logger.debug("input HEADER_SIZE:"+len);
		
		//判断输入的数据是否大于规定的头部长度，如果头部长度未达到，说明数据异常
		if (len > Constant.HEADER_SIZE) 
		{

			//准备头部读取存储空间
			byte[] headBuffer = new byte[Constant.HEADER_SIZE + 1];
			//将头部数据读出来
			System.arraycopy(buffer, 0, headBuffer, 0, Constant.HEADER_SIZE);
			
			//头部数据最后一个byte填充为0
			headBuffer[Constant.HEADER_SIZE] = 0;

			//准备好报文体部分的存储空间
			jsonBuffer = new byte[len - Constant.HEADER_SIZE];
			//将头部之后的数据(报文体)读出来
			System.arraycopy(buffer, Constant.HEADER_SIZE, jsonBuffer, 0, len
					- Constant.HEADER_SIZE);
			logger.debug("jsonBuffer: "
					+ jsonBuffer.toString());
			
			String[] headerStrList = null;
			try {
				//将头部数据处理为Key=value的字符串数组
				headerStrList = new String(headBuffer, "UTF-8").split("&");
			} catch (UnsupportedEncodingException e) {
				logger.error(Constant.MSG_HEADER_ERR);
				Response resp = new DefaultResponse();
				resp.setErrorCode(Constant.CODE_HEADER_ERR);
				resp.setErrorMsg(Constant.MSG_HEADER_ERR);
				resultJson = genJsonResp(resp);
				return resultJson;
			}
			//然后再将头部key=value的字符串数组中的参数和值全部解析出来存储为headerInfo对象
			//目前定义的头有7个字段
			if (headerStrList != null) {
				for (int i = 0; i < headerStrList.length; i++) {
					String[] kvStr = headerStrList[i].split("=");
					if (kvStr != null && kvStr.length == 2) {
						if (kvStr[0].compareTo("appId") == 0) {
							headerInfo.setAppId(kvStr[1]);
						} else if (kvStr[0].compareTo("method") == 0) {
							headerInfo.setMethod(kvStr[1]);
						} else if (kvStr[0].compareTo("lang") == 0) {
							headerInfo.setLang(kvStr[1]);
						} else if (kvStr[0].compareTo("sign") == 0) {
							headerInfo.setSign(kvStr[1]);
						} else if (kvStr[0].compareTo("uuId") == 0) {
							headerInfo.setUuId(kvStr[1]);
						} else if (kvStr[0].compareTo("version") == 0) {
							headerInfo.setVersion(kvStr[1]);
						} else if (kvStr[0].compareTo("timestamp") == 0) {
							headerInfo.setTimestamp(kvStr[1]);
						}
					}
				}
			}
			try {
				
			//  UUID uu=UUID.fromString(UUID.randomUUID().toString());
			//  logger.debug("uu:"						+ uu.toString());
			//	logger.debug("uu:"						+ uu.getLeastSignificantBits());
			//	//校验header签名信息
				if(1==2)
				{
					HeaderCheckImpl.execute(headerInfo);
				}
				

				//如果版本号送的是110，说明数据是加密的，需要先对报文体数据进行解密
				if (null != headerInfo.getVersion() && true == headerInfo.getVersion().equalsIgnoreCase("110")) {
					//取到UUID128位中的高64位，并取绝对值
					long number = Math.abs(UUID.fromString(headerInfo.getUuId()).getMostSignificantBits());
					int index = (int)(number % 10);
					//取到密钥
					String key = SecureUtil.getCryptKey(SecureUtil.getChallenge(index));
					//编码
					byte[] cryptedBuffer = Base64.decodeBase64(jsonBuffer);
					
					if (null == (jsonBuffer = SecureUtil.AESDecrypt(cryptedBuffer, key.getBytes(), useECBCrypto))) {
						useECBCrypto = true;
						jsonBuffer = SecureUtil.AESDecrypt(cryptedBuffer, key.getBytes(), useECBCrypto);
					}
				}
				
				//获取准备实现的对象方法名
				String method = headerInfo.getMethod();
				
				//生成实现类的名称
				StringBuffer implClassName = new StringBuffer();
				implClassName.append("com.health.mapp.impl.");
				implClassName.append(toUpperCaseInitial(method));
				implClassName.append("Impl");

				//对应的请求bean
				StringBuffer beanClassName = new StringBuffer();
				beanClassName.append("com.health.mapp.bean.");
				beanClassName.append(toUpperCaseInitial(method));
				beanClassName.append("Req");

				//统一的返回对象封装
				Response resp = null;
				try {
					
					logger.debug("implClassName: "
							+ implClassName.toString());
					//反射生成方法类对象
					Class<?> methodClass = Class.forName(implClassName
							.toString());
					//生成实际调用类的对象实例
					ActionInterface action = (ActionInterface) methodClass
							.newInstance();

					logger.debug("beanClassName: "
							+ beanClassName.toString());
					//反射生成请求类对象
					//这里是一个空的请求模板
					Class<?> reqClass = Class.forName(beanClassName.toString());
					
					//对象映射器
					ObjectMapper objectMapper = new ObjectMapper();
					objectMapper.disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES);  
					objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
					objectMapper.setSerializationInclusion(Inclusion.NON_NULL); 
					//要映射为的对象
					Object jsonBean = null;

					try {
						
						//将传入的key=value
					      StringBuffer sb = new StringBuffer();
					      //目前还没清楚为什么字节数组不能直接进行对象转换，所以先用字符串进行处理
					 	 for(int i=0;i<jsonBuffer.length;i++)
					 	 {
					 		//logger.debug("jsonBuffer-"+i+":"+ (char)jsonBuffer[i]);
					 		sb.append((char)jsonBuffer[i]);
					 	 }
					 	logger.debug("sb: "	+ sb);
						 String jsonString = "{\"imsi\":\"122\", \"imei\":12212}";
						// logger.debug("jsonBuffer:"+ jsonBuffer.toString());
						jsonBean = objectMapper.readValue(sb.toString(), reqClass);
						logger.debug("Request method: "	+ headerInfo.getMethod());
						logger.debug(String.format("Request bean: [%s]", request.getSession().getId() ));
						CommonsUtils.dumpObject(logger, jsonBean);
						headerInfo.setHttpRequest(getRequest());
						//处理业务
						resp = action.execute(headerInfo, jsonBean);
						
						
					} catch (JsonParseException e) {
						resp = new DefaultResponse();
						resp.setErrorCode(Constant.CODE_REQ_JSON_FORMAT_ERR);
						resp.setErrorMsg(Constant.MSG_REQ_JSON_FORMAT_ERR);
						resultJson = genJsonResp(resp);
						e.printStackTrace();
						logger.error(Constant.MSG_REQ_JSON_FORMAT_ERR +"["
								+ headerInfo.getMethod() + "]"
								+ new String(jsonBuffer));
					} catch (JsonMappingException e) {
						resp = new DefaultResponse();
						resp.setErrorCode(Constant.CODE_REQ_JSON_FORMAT_ERR);
						resp.setErrorMsg(Constant.MSG_REQ_JSON_FORMAT_ERR);
						resultJson = genJsonResp(resp);
						e.printStackTrace();
						logger.error(Constant.MSG_REQ_JSON_FORMAT_ERR+"["
								+ headerInfo.getMethod() + "]"
								+ new String(jsonBuffer));
					} catch (IOException e) {
						resp = new DefaultResponse();
						resp.setErrorCode(Constant.CODE_REQ_JSON_FORMAT_ERR);
						resp.setErrorMsg(Constant.MSG_REQ_JSON_FORMAT_ERR);
						resultJson = genJsonResp(resp);
						e.printStackTrace();
						logger.error(Constant.MSG_REQ_JSON_FORMAT_ERR+"["
								+ headerInfo.getMethod() + "]"
								+ new String(jsonBuffer));
					}  catch (Exception e) {
						resp = new DefaultResponse();
						resp.setErrorCode(Constant.CODE_REQ_MAPP_ERR);
						resp.setErrorMsg(Constant.MSG_REQ_MAPP_ERR);
						resultJson = genJsonResp(resp);
						logger.error(Constant.MSG_REQ_MAPP_ERR
								+ e.getLocalizedMessage());
						e.printStackTrace();
					}
					
					//处理为json 
					resultJson = genJsonResp(resp);
				
				
					
				} catch (ClassNotFoundException e) {
					resp = new DefaultResponse();
					resp.setErrorCode(Constant.CODE_REQ_METHOD_NOT_SUPPORT);
					resp.setErrorMsg(Constant.MSG_REQ_METHOD_NOT_SUPPORT);
					resultJson = genJsonResp(resp);
					logger.error(Constant.MSG_REQ_METHOD_NOT_SUPPORT + headerInfo.getMethod());
				} catch (InstantiationException e) {
					resp = new DefaultResponse();
					resp.setErrorCode(Constant.CODE_REQ_METHOD_ERR);
					resp.setErrorMsg(Constant.MSG_REQ_METHOD_ERR);
					resultJson = genJsonResp(resp);
					logger.error(Constant.MSG_REQ_METHOD_ERR + headerInfo.getMethod());
				} catch (IllegalAccessException e) {
					resp = new DefaultResponse();
					resp.setErrorCode(Constant.CODE_REQ_METHOD_ERR);
					resp.setErrorMsg(Constant.MSG_REQ_METHOD_ERR);
					resultJson = genJsonResp(resp);
					logger.error(Constant.MSG_REQ_METHOD_ERR + headerInfo.getMethod());
				}

			} catch (MappException e) {
				resultJson = genJsonResp(e.result());
			}
		} 
		else {
			//没有头部
			//直接返回请求方法为空，头部解析错误
			Response resp = new DefaultResponse();
			resp.setErrorCode(Constant.CODE_HEADER_ERR);
			resp.setErrorMsg(Constant.MSG_HEADER_ERR);
			resultJson = genJsonResp(resp);
			logger.error(Constant.MSG_HEADER_ERR);
		}
		
		logger.debug(String.format("RESP: %s[%s]", resultJson, request.getSession().getId() ));
		
		//如果是加密版本，需要将返回的数据进行加密再返回
		if (null != headerInfo.getVersion() && true == headerInfo.getVersion().equalsIgnoreCase("110")) {
			try {
				int number = Integer.valueOf(headerInfo.getTimestamp().substring(10));
				int index = number % 10;
				String key = SecureUtil.getCryptKey(SecureUtil.getChallenge(index));
				byte[] cryptedBuffer = SecureUtil.AESEncrypt(resultJson.getBytes("UTF-8"), key.getBytes(), useECBCrypto);
				resultJson = new String(Base64.encodeBase64(cryptedBuffer));
//				logger.debug("cryptedResponse=" + resultJson);
			} catch (Exception e) {
				e.printStackTrace();
				resultJson = "";
			}
		}

		return resultJson;
	}

	/**
	 * @param resp
	 * @return
	 */
	public static String genJsonResp(Response o) {
		String result = null;
		ObjectMapper objectMapper = new ObjectMapper();
		//版本2.x
         //		Jackson 序列化 如何让为NULL的属性不参与序列化
		objectMapper.setSerializationInclusion(Inclusion.NON_NULL); 
		JsonGenerator jsonGenerator = null;
		ByteArrayOutputStream out = null;
		try {
			out = new ByteArrayOutputStream();

			//
			jsonGenerator = objectMapper.getJsonFactory().createJsonGenerator(
					out, JsonEncoding.UTF8);
			jsonGenerator.writeObject(o);
			result = out.toString("UTF-8");
			out.flush();
			out.close();
		} catch (IOException e1) {
			result = "{\"errorCode\":100,\"errorMsg\":\"System error.\"}";
		}
		return result;
	}

	/**
	 * @param srcString
	 * @return
	 */
	private static String toUpperCaseInitial(String srcString) {
		StringBuilder sb = new StringBuilder();
		sb.append(Character.toUpperCase(srcString.charAt(0)));
		sb.append(srcString.substring(1));
		return sb.toString();
	}

}
